﻿using System;
using System.Data;
using System.Data.OleDb;
using System.Windows.Forms;
using System.Configuration;
using System.Xml;
using System.IO;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Data.Common;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;


namespace UDPServer
{

    /// <summary>
    /// 配置文件的读写基础类。
    /// </summary>
    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public class ParamBase
    {  
        static ParamBase pmBase = null;
        
        DataSet dsConfig = null; 
         
        string strConfigVersion = "1.0";

        Mutex m_mut = new Mutex();   //保存文件的互斥体

        private ParamBase()
        {
            LoadConfig();
        }

        public static ParamBase Create()
        {
            if (null == ParamBase.pmBase)
            {
                ParamBase.pmBase = new ParamBase();
            }

            return ParamBase.pmBase;

        }


        /// <summary>
        /// 指示配置文件是否存在
        /// </summary>
        public bool ConfigFileExist
        {
            get;
            set;
        }

        /// <summary>
        /// 本程序结构当前的,配置文件版本号
        /// (本软件当前使用的配置文件版本号)
        /// </summary>
        public string ConfigVersion
        {
            get { return strConfigVersion; }
        }

        /// <summary>
        /// 当前读取的配置文件的版本号
        /// (从配置文件中读取的版本号, 是老的版本号)
        /// </summary>
        public string FileConfigVersion
        {
            get { return GetKeyByConfig("ConfigVersion"); }
        }



        #region 读写系统节配置文件

        /// <summary>
        /// 加载配置文件
        /// </summary>
        public void LoadConfig()
        {
            ConfigFileExist = true;
            //dsConfig = null;
            string strpath = System.Windows.Forms.Application.ExecutablePath + ".xml";
            if (!File.Exists(strpath))
            {
                dsConfig = ConstructConfig();
                ConfigFileExist = false;
            }
            else
            {
                if (dsConfig == null) dsConfig = new DataSet();

                FileStream fs = new FileStream(strpath, FileMode.Open);
                if (fs.Length < 10)
                {
                    fs.Close();
                    fs = null; 
                    throw new Exception( ("配置文件已损坏，请检查或删除后重新打开软件！"));  
                }
                dsConfig.ReadXml(fs);
                fs.Close();
            }

        }

        /// <summary>
        /// 保存配置文件
        /// </summary>
        public void Save()
        {
            m_mut.WaitOne();

            string strpath = System.Windows.Forms.Application.ExecutablePath + ".xml";
            FileStream fs = new FileStream(strpath, FileMode.Create); 
            dsConfig.WriteXml(fs, XmlWriteMode.IgnoreSchema);
            fs.Close();

            m_mut.ReleaseMutex();
        }

        private DataSet ConstructConfig()
        {
            DataSet ds = new DataSet("configuration");
            DataTable dt = ds.Tables.Add("appSettings");
            dt.Columns.Add("name");
            dt.Columns.Add("value");
            DataRow dr = dt.NewRow();
            dr[0] = "ConfigVersion";
            dr[1] = ConfigVersion;
            dr.EndEdit();
            dt.Rows.Add(dr);
              
            return ds;
        }
        /// <summary>
        /// 读取appSettings表下面字段
        /// </summary>
        /// <param name="key">字段名称</param>
        /// <returns>返回字段值</returns>
        public string GetKeyByConfig(string key)
        {
            m_mut.WaitOne();
            string SectionName = "appSettings";
            string vals = "";

            if (dsConfig.Tables[SectionName] != null && dsConfig.Tables[SectionName].Rows.Count > 0)
            {
                DataView dv = new DataView(dsConfig.Tables[SectionName]);
                dv.RowFilter = "name='" + key + "'";
                if (dv.Count > 0)
                {
                    if (dv[0][1] != null) vals = dv[0][1].ToString();
                }
            }
            m_mut.ReleaseMutex();
            return vals;
        }

        /// <summary>
        ///  读取appSettings表下面字段
        /// </summary>
        /// <param name="key">字段名称</param>
        /// <param name="strdefault">默认值，如果字段为空，则按默认值返回</param>
        /// <returns>返回字段值,如果字段为空，则按默认值返回</returns>
        public string GetKeyByConfig(string key, string strdefault)
        {
            string vals = GetKeyByConfig(key);
            if (vals == "") vals = strdefault;
            return vals;
        }

        /// <summary>
        /// 设置appSettings表下面字段
        /// </summary>
        /// <param name="key"></param>
        /// <param name="vals"></param>
        public void SetKeyByConfig(string key, string vals)
        {
            m_mut.WaitOne();

            string SectionName = "appSettings";
            DataView dv = new DataView(dsConfig.Tables[SectionName]);
            dv.RowFilter = "name='" + key + "'";
            if (dv.Count > 0)
            {
                dv[0][1] = vals;
            }
            else
            {
                DataRowView drv = dv.AddNew();
                drv["name"] = key;
                drv["value"] = vals;
                drv.EndEdit();
            }

            m_mut.ReleaseMutex();
        }
        /// <summary>
        /// 读取SectionName表下面的字段
        /// </summary>
        /// <param name="SectionName">表名</param>
        /// <param name="Property">字段名</param>
        /// <returns>返回字段值</returns>
        public String GetValue(String SectionName, String Property)
        {
            string ret = "";
            m_mut.WaitOne();

            if (dsConfig.Tables[SectionName] != null && dsConfig.Tables[SectionName].Rows.Count > 0)
            {
                if (dsConfig.Tables[SectionName].Columns.Contains(Property))
                {
                    ret = dsConfig.Tables[SectionName].Rows[0][Property].ToString();
                }
            }
            m_mut.ReleaseMutex();

            return ret;
        }



        #endregion

        #region 读写独立节配置文件

        public bool GetValue(String SectionName, String Property, String strDefault, bool bvalue)
        {
            string vals = GetValue(SectionName, Property);
            if (vals == "") vals = strDefault;

            return vals == "1" ? true : false;
        }
        public int GetValue(String SectionName, String Property, String strDefault, int ivalue)
        {
            string vals = GetValue(SectionName, Property);
            if (vals == "") vals = strDefault;

            int.TryParse(vals, out ivalue);
            return ivalue;
        }
        public float GetValue(String SectionName, String Property, String strDefault, float fvalue)
        {
            string vals = GetValue(SectionName, Property);
            if (vals == "") vals = strDefault;

            float.TryParse(vals, out fvalue);
            return fvalue;
        }
        public string GetValue(String SectionName, String Property, String strDefault, string strvalue)
        {
            string vals = GetValue(SectionName, Property);
            if (vals == "") vals = strDefault;

            return vals;
        }
        public float[] GetValue(String SectionName, String Property, String strDefault, float[] fvalueList)
        {
            string vals = GetValue(SectionName, Property);
            if (vals == "") vals = strDefault;

            string[] strList = vals.Split(' ');
            float[] fvalList = new float[strList.Length];
            for (int i = 0; i < strList.Length; i++)
            {
                float.TryParse(strList[i], out fvalList[i]);
            }
            return fvalList;
        }
        public int[] GetValue(String SectionName, String Property, String strDefault, int[] fvalueList)
        {
            string vals = GetValue(SectionName, Property);
            if (vals == "") vals = strDefault;

            string[] strList = vals.Split(' ');
            int[] fvalList = new int[strList.Length];
            for (int i = 0; i < strList.Length; i++)
            {
                int.TryParse(strList[i], out fvalList[i]);
            }
            return fvalList;
        }

        /// <summary>
        /// 读取SectionName表下面的字段
        /// </summary>
        /// <param name="SectionName">表名</param>
        /// <param name="Property">字段名</param>
        /// <param name="strDefault">默认值，如果字段为空，则按默认值返回</param>
        /// <returns>返回字段值，如果字段为空，则按默认值返回</returns>
        public String GetValue(String SectionName, String Property, String strDefault)
        {
            string vals = GetValue(SectionName, Property);
            if (vals == "") vals = strDefault;

            return vals;
        }

        public void SetValue(String SectionName, String Property, int value)
        {
            SetValue(SectionName, Property, value.ToString());
        }
        public void SetValue(String SectionName, String Property, float value)
        {
            SetValue(SectionName, Property, value.ToString());
        }
        public void SetValue(String SectionName, String Property, double value)
        {
            SetValue(SectionName, Property, value.ToString());
        }
        public void SetValue(String SectionName, String Property, bool value)
        {
            SetValue(SectionName, Property, value ? "1" : "0");
        }
        public void SetValue(String SectionName, String Property, Color value)
        {
            SetValue(SectionName, Property, value.ToArgb().ToString());
        }
        public void SetValue(String SectionName, String Property, float[] valueList)
        {
            string str = "";
            for (int i = 0; i < valueList.Length; i++)
            {
                str += valueList[i] + " ";
            }
            str = str.TrimEnd();
            SetValue(SectionName, Property, str);
        }
        public void SetValue(String SectionName, String Property, int[] valueList)
        {
            string str = "";
            for (int i = 0; i < valueList.Length; i++)
            {
                str += valueList[i] + " ";
            }
            str = str.TrimEnd();
            SetValue(SectionName, Property, str);
        }
     

        /// <summary>
        /// 设置SectionName表下面字段
        /// </summary>
        /// <param name="SectionName"></param>
        /// <param name="Property"></param>
        /// <param name="value"></param>
        public void SetValue(String SectionName, String Property, String value)
        {
            m_mut.WaitOne();

            DataTable dt0 = dsConfig.Tables[SectionName];
            if (dt0 == null)  //如果没有该表，则重建该表
            {
                dt0 = dsConfig.Tables.Add(SectionName);
                DataColumn dtc = dt0.Columns.Add(Property);
                object[] obj = new object[1];
                obj[0] = value;

                dt0.Rows.Add(obj);
                m_mut.ReleaseMutex();
                return;
            }

            if (!dsConfig.Tables[SectionName].Columns.Contains(Property))  //如果没有该列，则重建该列
            {
                DataColumn dtc = dt0.Columns.Add(Property);
                if (dt0.Rows.Count > 0)
                {
                    dsConfig.Tables[SectionName].Rows[0][Property] = value;
                }
                else
                {
                    DataView dv = new DataView(dsConfig.Tables[SectionName]);
                    DataRowView drv = dv.AddNew();
                    drv[Property] = value;
                    drv.EndEdit();
                }

                m_mut.ReleaseMutex();
                return;
            }

            if (dsConfig.Tables[SectionName].Rows.Count == 0)
            {
                DataView dv = new DataView(dsConfig.Tables[SectionName]);
                DataRowView drv = dv.AddNew();
                drv[Property] = value;
                drv.EndEdit();

                m_mut.ReleaseMutex();
                return;
            }

            dsConfig.Tables[SectionName].Rows[0][Property] = value;
            m_mut.ReleaseMutex();
        }

        #endregion

        #region 读写字典类文件

         
        /// <summary>
        /// 读取SectionName表下面的所有字段
        /// </summary>
        /// <param name="SectionName"></param>
        /// <returns></returns>
        public Dictionary<String, String> GetProperties(String SectionName)
        {
            m_mut.WaitOne();
            Dictionary<String, String> ret = new Dictionary<string, string>();
            for (int i = 0; i < dsConfig.Tables[SectionName].Rows[0].ItemArray.Length; i++)
                ret.Add(dsConfig.Tables[SectionName].Columns[i].Caption, dsConfig.Tables[SectionName].Rows[0].ItemArray[i].ToString());
            m_mut.ReleaseMutex();
            return ret;
        }
        public void SetProperties(String SectionName, Dictionary<String, String> value)
        {
            m_mut.WaitOne();

            foreach (KeyValuePair<string, string> kvp in value)
                SetValue(SectionName, kvp.Key, kvp.Value);

            m_mut.ReleaseMutex();
        }

        /// <summary>
        /// 清空表(节Section)内容
        /// </summary>
        /// <param name="SectionName"></param>
        public void ClearSection(String SectionName)
        {
            m_mut.WaitOne();

            if (dsConfig.Tables[SectionName] != null && dsConfig.Tables[SectionName].Rows.Count > 0)
            {
                dsConfig.Tables[SectionName].Clear();
            }
            m_mut.ReleaseMutex();
        }

        #endregion 

        #region 读写表类列表文件

        /// <summary>
        /// 获取配置参数表格(表格类配置文件用到)
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public DataTable GetTable(string tableName, int ncol)
        {
            DataTable dt = null;
            m_mut.WaitOne();

            if (dsConfig.Tables[tableName] != null )
            {
                dt = dsConfig.Tables[tableName];
            }
            else
            {
                dt = dsConfig.Tables.Add(tableName);
                for( int i=0; i< ncol; i++)
                {
                    dt.Columns.Add("col"+i);
                } 
            }

            int icol = dt.Columns.Count;
            while (icol < ncol)
            {
                DataColumn dtc = dt.Columns.Add("col" + icol);
                icol++;
            }
            m_mut.ReleaseMutex();
            return dt;
        }
 

        public string[] GetTableRow(string tableName, params string[] param)
        {
            int nparam = param.Length;
            string[] strList = null;
            DataTable dt = GetTable(tableName, nparam);
            if (dt == null) return strList;

            m_mut.WaitOne();

            int ncol = dt.Columns.Count;
            string keyValue = param[0];
            DataView dv = dt.DefaultView;
            dv.RowFilter =  "col0='"+ keyValue + "'";
            if (dv.Count > 0)
            {
                strList = new string[ncol];
                for( int i=0; i<ncol; i++)
                {
                    strList[i] = dv[0][i].ToString();
                } 
            }

            m_mut.ReleaseMutex();

            if (strList == null) strList = param;
            return strList;
        }

        public void SetTableRow(string tableName, params string[] param)
        {
            int nparam = param.Length; 
            DataTable dt = GetTable(tableName, nparam);
            if (dt == null) return  ;

            m_mut.WaitOne();

            int ncol = Math.Min( dt.Columns.Count, param.Length);
            string keyValue = param[0];
            DataView dv = dt.DefaultView;
            dv.RowFilter = "col0='" + keyValue + "'";
            if (dv.Count > 0)
            { 
                for (int i = 0; i < ncol; i++)
                {
                    dv[0][i] = param[i]  ;
                }
                dv[0].EndEdit();
            }
            else
            {
                DataRowView drv = dv.AddNew();
                for (int i = 0; i < ncol; i++)
                {
                    drv[i] = param[i];
                }
                drv.EndEdit();
            }

            m_mut.ReleaseMutex();


        }

        #endregion

    }





}
